import {
  BadRequestException,
  Body,
  Controller,
  Get,
  Inject,
  Post,
  Query,
  Req,
  Request,
  UnauthorizedException,
} from '@nestjs/common'
import { JwtService } from '@nestjs/jwt'
import { ApiBody, ApiOperation, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger'
import { AppService } from './app.service'
import { ResData, SimpleUser, User } from './model/result.dto'
import { UserDto } from './model/user.dto'
import { delay } from './utils'
import { ApiResDataGetResponse } from './utils/swagger.utils'

const users = [
  { username: 'uni_fteam', password: 'uni_fteam@123', email: 'fteam@fteam.cc' },
]

@Controller('')
@ApiTags('uniApi')
export class AppController {
  constructor(private readonly appService: AppService) {
  }

  @Inject(JwtService)
  private jwtService: JwtService

  /* get 测试 */
  @Get('getTestWithKey')
  @ApiOperation({ summary: '获取测试数据（带自定义KEY）' })
  @ApiResDataGetResponse(SimpleUser, '请求成功')
  getTestWithKey() {
    return {
      success: 1,
      fteam: {
        userName: '这是自定义KEY的结果',
      },
      msg: '我是消息',
    }
  }

  /* get 测试 */
  @Get('getTest')
  @ApiOperation({ summary: '获取测试数据', description: '返回用户信息和查询参数' })
  @ApiQuery({ name: 'query', required: false, description: '查询参数' })
  @ApiResDataGetResponse(User, '用户创建成功')
  getTest(@Query() query: any) {
    return {
      code: 200,
      data: {
        userName: 'uni-app',
        userId: 'ft151512135155',
        accessToken: 'cc15f1as15d61as1fd5',
        refreshToken: 'dd1s5d1f51as5df61a5f5d16',
        query,
      },
      message: 'success',
    } as ResData<any>
  }

  @Get('longRequest')
  @ApiOperation({ summary: '模拟长请求', description: '延迟3秒后返回数据' })
  @ApiQuery({ name: 'query', required: false, description: '查询参数' })
  @ApiResponse({ status: 200, description: '成功获取延迟数据' })
  async longRequest(@Query() query: any) {
    /* 延迟 3s 返回数据 */
    return new Promise((resolve) => {
      setTimeout(() => {
        const resData = {
          code: 200,
          data: query,
          message: '这是延迟 3 秒后返回的数据',
        } as ResData<any>
        resolve(resData)
      }, 3000)
    })
  }

  /* post 测试 */
  @Post('v1/list_session')
  @ApiOperation({ summary: '获取会话列表' })
  @ApiResponse({ status: 500, description: '服务器处理失败' })
  listSession() {
    return {
      code: 500,
      message: '服务器请求处理失败',
      data: 'API responded with status: ',
    } as ResData<any>
  }

  /* post 测试 */
  @Post('v1/chat')
  @ApiOperation({ summary: '聊天接口' })
  @ApiResponse({ status: 500, description: '服务器处理失败' })
  chat() {
    return {
      code: 500,
      message: '服务器请求处理失败',
      data: {
        type: 'text',
        content: 'API responded with status: ',
      },
    } as ResData<any>
  }

  /* post 测试 */
  @Post('postTest')
  @ApiOperation({ summary: 'POST测试接口', description: '测试POST请求并返回数据' })
  @ApiQuery({ name: 'query', required: false, description: '查询参数' })
  @ApiBody({ type: Object, description: '请求体数据' })
  @ApiResponse({ status: 200, description: '成功处理POST请求' })
  postTest(@Query() query: any, @Body() data: Body) {
    return {
      code: 200,
      data: {
        userName: 'uni-app',
        userId: 'sfc151512135155',
        accessToken: 'sd15f1as15d61as1fd5',
        refreshToken: '1s5d1f51as5df61a5f5d16',
        data,
        query,
      },
      message: 'PostTest 消息',
    } as ResData<any>
  }

  /* 登录接口，获取 token */
  @Post('login')
  @ApiOperation({ summary: '用户登录', description: '用户登录并获取token' })
  @ApiBody({ type: UserDto, description: '用户登录信息' })
  @ApiResponse({ status: 200, description: '登录成功' })
  @ApiResponse({ status: 400, description: '用户不存在或密码错误' })
  login(@Body() userDto: UserDto) {
    const user = users.find(item => item.username === userDto.username)

    if (!user) {
      throw new BadRequestException('用户不存在')
    }

    if (user.password !== userDto.password) {
      throw new BadRequestException('密码错误')
    }

    const accessToken = this.jwtService.sign(
      {
        username: user.username,
        email: user.email,
      },
      {
        expiresIn: 60,
      },
    )

    const refreshToken = this.jwtService.sign(
      {
        username: user.username,
      },
      {
        expiresIn: 24 * 60 * 60,
      },
    )

    return {
      message: '成功',
      code: 200,
      data: {
        userInfo: {
          username: user.username,
          email: user.email,
        },
        accessToken,
        refreshToken,
      },
    } as ResData<any>
  }

  /* 获取用户信息 */
  @Get('userInfo')
  @ApiOperation({ summary: '获取用户信息', description: '根据token获取用户详细信息' })
  @ApiResponse({ status: 200, description: '成功获取用户信息' })
  @ApiResponse({ status: 401, description: '未登录或token失效' })
  getUserInfo(@Req() req: Request) {
    // @ts-ignore
    const authorization = req.headers.authorization as string

    if (!authorization) {
      throw new UnauthorizedException('用户未登录')
    }

    try {
      const token = authorization.split(' ')[1]
      const data = this.jwtService.verify(token)

      return {
        message: 'success',
        code: 200,
        data,
      } as ResData<any>
    } catch (_) {
      throw new UnauthorizedException('token 失效，请重新登录, userInfo')
    }
  }

  /* 刷新 token */
  @Get('refresh')
  @ApiOperation({ summary: '刷新Token', description: '使用refreshToken刷新accessToken' })
  @ApiQuery({ name: 'refreshToken', required: true, description: '刷新令牌' })
  @ApiResponse({ status: 200, description: '成功刷新token' })
  @ApiResponse({ status: 401, description: 'token失效' })
  async refresh(@Query('refreshToken') token: string) {
    try {
      const data = this.jwtService.verify(token)

      const user = users.find(item => item.username === data.username)

      const accessToken = this.jwtService.sign(
        {
          username: user.username,
          email: user.email,
        },
        {
          expiresIn: 60,
        },
      )

      const refreshToken = this.jwtService.sign(
        {
          username: user.username,
        },
        {
          expiresIn: 60 * 60 * 24,
        },
      )
      await delay(2000)
      return {
        message: '刷新成功',
        code: 200,
        data: {
          accessToken,
          refreshToken,
        },
      } as ResData<any>
    } catch (_) {
      throw new UnauthorizedException('token 失效，请重新登录 Refresh')
    }
  }

  /* 获取测试列表 */
  @Get('testList')
  @ApiOperation({ summary: '获取测试列表', description: '获取测试数据列表' })
  @ApiQuery({ name: 'page', required: false, description: '当前页' })
  @ApiQuery({ name: 'limit', required: false, description: '每页条数' })
  @ApiResponse({ status: 200, description: '成功获取测试列表' })
  async getTestList(@Query('page') page: number = 1, @Query('limit') limit: number = 10) {
    // _page=1&_limit=10
    const listData = await this.appService.getList(page, limit)
    return {
      message: '操作成功',
      code: 200,
      data: listData,
    } as ResData<any>
  }
}
